package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.apis.article.IArticleClient;
import com.heima.common.constants.WemediaConstants;
import com.heima.common.constants.WmNewsMessageConstants;
import com.heima.common.exception.CustomException;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.VoDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.*;
import com.heima.model.wemedia.utils.WmThreadLocalUtils;
import com.heima.wemedia.mapper.*;
import com.heima.wemedia.service.WmNewsService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
public class WmNewsImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {


    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;
    @Autowired
    private WmMaterialMapper wmMaterialMapper;
    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;
    @Autowired
    private WmNewsMapper wmNewsMapper;
    @Autowired
    private WmchannelMapper wmchannelMapper;
    @Autowired
    private WmUserMapper wmUserMapper;
    @Autowired
    private IArticleClient iArticleClient;



    @Override
    public ResponseResult getNew(WmNewsPageReqDto wmNewsPageReqDto) {
        //1.检查参数
        if(wmNewsPageReqDto == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        Page page = new Page(wmNewsPageReqDto.getPage(),wmNewsPageReqDto.getSize());

        LambdaQueryWrapper<WmNews> lqw = new LambdaQueryWrapper<>();
        //状态精确查询
       if (wmNewsPageReqDto.getStatus() != null){
            lqw.eq(WmNews::getStatus,wmNewsPageReqDto.getStatus());
       }

        //频道精确查询
        if(wmNewsPageReqDto.getChannelId() != null){
            lqw.eq(WmNews::getChannelId,wmNewsPageReqDto.getChannelId());
        }

        //时间范围查询
        if (wmNewsPageReqDto.getBeginPubDate()!=null && wmNewsPageReqDto.getEndPubDate()!=null){
            lqw.between(WmNews::getPublishTime,wmNewsPageReqDto.getBeginPubDate(),wmNewsPageReqDto.getEndPubDate());
        }

        //关键字模糊查询
        if(StringUtils.isNotBlank(wmNewsPageReqDto.getKeyword())){
            lqw.like(WmNews::getTitle,wmNewsPageReqDto.getKeyword());
        }

        //查询当前登录用户的文章
        lqw.eq(WmNews::getUserId,WmThreadLocalUtils.getUser().getId());

        //发布时间倒序查询
        lqw.orderByDesc(WmNews::getCreatedTime);

        page = page(page,lqw);

        ResponseResult responseResult = new PageResponseResult(wmNewsPageReqDto.getPage(),wmNewsPageReqDto.getSize(),(int)page.getTotal());
        responseResult.setData(page.getRecords());

        return responseResult;
    }

    /**
     * 文章发布
     * @param wmNewsDto
     * @return
     */
    @Override
    public ResponseResult submitNews(WmNewsDto wmNewsDto) {
        //0.参数处理
        if (wmNewsDto==null || wmNewsDto.getContent() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        WmNews wmNews = new WmNews();
        BeanUtils.copyProperties(wmNewsDto,wmNews);

        //1.封面图片
        if(wmNewsDto.getImages() != null && wmNewsDto.getImages().size() > 0){
            String imageStr = StringUtils.join(wmNewsDto.getImages(), ",");
            wmNews.setImages(imageStr);
        }
        //如果当前的封面传来的值为-1(自动封面)
        if (wmNewsDto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){
            //数据库中设置了字段不能为负,故若为-1
            wmNews.setType(null);
        }

        saveOrUpdateWmNews(wmNews);

        //2.判断是否为草稿如果为草稿结束当前方法
        if (wmNewsDto.getStatus().equals(WmNews.Status.NORMAL.getCode())){
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }

        //3.不是草稿，保存文章内容图片与素材的关系
        //获取到文章内容中的图片信息
        List<String> materials = ectractUrlInfo(wmNewsDto.getContent());

        //4.不是草稿，保存文章封面图片与素材的关系，如果当前布局是自动，需要匹配封面图片
        saveRelativeInfoForCover(wmNewsDto,wmNews,materials);

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 文章下架
     * @param dto
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNewsDto dto) {
        //检查参数
        if (dto.getId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //根据id获取文章
        WmNews wmNews = getById(dto.getId());
        if (wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"文章不存在");
        }
        //判断文章是否已经发布
        if (!wmNews.getStatus().equals(WmNews.Status.PUBLISHED.getCode())){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"文章不未上架,不能下架");
        }

        //4.修改文章enable
        if (dto.getEnable()!=null && dto.getEnable()>-1 && dto.getEnable() < 2){
            wmNews.setEnable(dto.getEnable());
            updateById(wmNews);
        }

        //通知另一端修改文章配置
        if (wmNews.getArticleId()!=null){
            Map<String,Object> map = new HashMap<>();
            map.put("articleId",wmNews.getArticleId());
            map.put("enable",dto.getEnable());

            kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC,JSON.toJSONString(map));
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 查询文章列表
     *
     * @param voDto
     * @return
     */
    @Override
    public ResponseResult getList(VoDto voDto) {
        if (voDto.getPage()==0 || voDto.getSize()==0){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        IPage<WmNews> page = new Page<>(voDto.getPage(), voDto.getSize());

        wmNewsMapper.selectPage(page,Wrappers.<WmNews>lambdaQuery()
                .eq(!voDto.getStatus().equals(""),WmNews::getStatus,voDto.getStatus())
                .like(WmNews::getTitle,voDto.getTitle())
        );


        PageResponseResult pageResponseResult = new PageResponseResult((int)page.getCurrent(),(int)page.getSize(),(int)page.getTotal());
        pageResponseResult.setData(page.getRecords());
        return pageResponseResult;
    }

    /**
     * 查询文章详情
     *
     * @param id
     * @return
     */
    @Override
    public ResponseResult getNewOne(Integer id) {
        if (id == 0){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        WmNews wmNews = wmNewsMapper.selectOne(Wrappers.<WmNews>lambdaQuery().eq(WmNews::getId, id));
        return ResponseResult.okResult(wmNews);
    }

    /**
     * 审核失败
     *
     * @param map
     * @return
     */
    @Override
    public ResponseResult authFail(Map<String, Object> map) {
        if (map.size()==0){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews wmNews = wmNewsMapper.selectOne(Wrappers.<WmNews>lambdaQuery().eq(WmNews::getId, map.get("id")));
        wmNews.setReason(map.get("msg").toString());
        wmNews.setStatus((short)2);
        wmNewsMapper.updateById(wmNews);

        return ResponseResult.okResult("驳回成功");
    }

    /**
     * 审核成功
     * @param map
     * @return
     */
    @Override
    public ResponseResult authPass(Map<String, Object> map) {
        if (map.size()==0){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews wmNews = wmNewsMapper.selectOne(Wrappers.<WmNews>lambdaQuery().eq(WmNews::getId, map.get("id")));
        wmNews.setStatus((short)9);



//        //调用文章发布
//        wmNewsService.submitNews(wmNewsDto);
        ResponseResult responseResult = saveAppArticle(wmNews);


        //回填article_id
        wmNews.setArticleId((Long) responseResult.getData());

        wmNewsMapper.updateById(wmNews);

        return ResponseResult.okResult("通过成功");
    }

    /**
     * 审核成功,保存app端文章信息
     * @param wmNews
     */
    private ResponseResult saveAppArticle(WmNews wmNews) {
        ArticleDto dto = new ArticleDto();
        //属性拷贝
        BeanUtils.copyProperties(wmNews,dto);
        //文章的布局
        dto.setLayout(wmNews.getType());
        //频道
        WmChannel wmChannel = wmchannelMapper.selectById(wmNews.getChannelId());
        if (wmChannel!=null){
            dto.setChannelName(wmChannel.getName());
        }
        //作者信息
        dto.setAuthorId(wmNews.getUserId().longValue());
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
        if (wmUser!=null){
            dto.setAuthorName(wmUser.getName());
        }

        //设置文章id
        if (wmNews.getArticleId() != null){
            dto.setId(wmNews.getArticleId());
        }
        dto.setCreatedTime(new Date());

        ResponseResult responseResult = iArticleClient.saveArticle(dto);
        return responseResult;

    }



    private void saveRelativeInfoForCover(WmNewsDto wmNewsDto, WmNews wmNews, List<String> materials) {
        List<String> images = wmNewsDto.getImages();

        //如果当前封面类型为自动，则设置封面类型的数据
        if(wmNewsDto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){
            //多图
            if(materials.size() >= 3){
                wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);
                images = materials.stream().limit(3).collect(Collectors.toList());
            }else if(materials.size() >= 1 && materials.size() < 3){
                //单图
                wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);
                images = materials.stream().limit(1).collect(Collectors.toList());
            }else {
                //无图
                wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);
            }

            //修改文章
            if(images != null && images.size() > 0){
                wmNews.setImages(StringUtils.join(images,","));
            }
            updateById(wmNews);
        }
        if(images != null && images.size() > 0){
            saveRelativeInfo(images,wmNews.getId(),WemediaConstants.WM_COVER_REFERENCE);
        }
    }

    private void saveRelativeInfo(List<String> materials, Integer newsId, Short type) {
        if(materials!=null && !materials.isEmpty()){
            //通过图片的url查询素材的id
            List<WmMaterial> dbMaterials = wmMaterialMapper.selectList(Wrappers.<WmMaterial>lambdaQuery().in(WmMaterial::getUrl, materials));

            //判断素材是否有效
            if(dbMaterials==null || dbMaterials.size() == 0){
                //手动抛出异常   第一个功能：能够提示调用者素材失效了，第二个功能，进行数据的回滚
                throw new CustomException(AppHttpCodeEnum.MATERIASL_REFERENCE_FAIL);
            }

            if(materials.size() != dbMaterials.size()){
                throw new CustomException(AppHttpCodeEnum.MATERIASL_REFERENCE_FAIL);
            }

            List<Integer> idList = dbMaterials.stream().map(WmMaterial::getId).collect(Collectors.toList());

            //批量保存
            wmNewsMaterialMapper.saveRelations(idList,newsId,type);
        }
    }


    private List<String> ectractUrlInfo(String content) {
        List<String> list = new ArrayList<>();
        List<Map> maps = JSON.parseArray(content, Map.class);
        for (Map map : maps) {
            if (map.get("type").equals("image")){
                String imgUrl = (String) map.get("value");
                list.add(imgUrl);
            }
        }
        return list;
    }


    private void saveOrUpdateWmNews(WmNews wmNews) {
        wmNews.setUserId(WmThreadLocalUtils.getUser().getId());
        wmNews.setCreatedTime(new Date());
        wmNews.setSubmitedTime(new Date());
        wmNews.setEnable((short)1);//默认上架

        if (wmNews.getId() == null){
            //没有id新增文章
            save(wmNews);
        }else {
            //修改文章内容
            wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId,wmNews.getId()));
            updateById(wmNews);
        }
    }
}
